package com.kexio.common.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

/**
 * JSON工具类
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
public class JsonUtils {
    
    /**
     * 默认ObjectMapper实例
     */
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    
    static {
        // 配置ObjectMapper
        OBJECT_MAPPER.registerModule(new JavaTimeModule());
        OBJECT_MAPPER.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        OBJECT_MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        OBJECT_MAPPER.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
    }
    
    private JsonUtils() {
        // 工具类不允许实例化
    }
    
    // ==================== 对象转JSON ====================
    
    /**
     * 对象转JSON字符串
     */
    public static String toJson(Object obj) {
        if (obj == null) {
            return null;
        }
        
        try {
            return OBJECT_MAPPER.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("对象转JSON失败", e);
        }
    }
    
    /**
     * 对象转格式化的JSON字符串
     */
    public static String toPrettyJson(Object obj) {
        if (obj == null) {
            return null;
        }
        
        try {
            return OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("对象转JSON失败", e);
        }
    }
    
    /**
     * 对象转JSON字节数组
     */
    public static byte[] toJsonBytes(Object obj) {
        if (obj == null) {
            return null;
        }
        
        try {
            return OBJECT_MAPPER.writeValueAsBytes(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("对象转JSON字节数组失败", e);
        }
    }
    
    // ==================== JSON转对象 ====================
    
    /**
     * JSON字符串转对象
     */
    public static <T> T fromJson(String json, Class<T> clazz) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        
        try {
            return OBJECT_MAPPER.readValue(json, clazz);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON转对象失败", e);
        }
    }
    
    /**
     * JSON字符串转对象（支持泛型）
     */
    public static <T> T fromJson(String json, TypeReference<T> typeReference) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        
        try {
            return OBJECT_MAPPER.readValue(json, typeReference);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON转对象失败", e);
        }
    }
    
    /**
     * JSON字节数组转对象
     */
    public static <T> T fromJson(byte[] jsonBytes, Class<T> clazz) {
        if (jsonBytes == null || jsonBytes.length == 0) {
            return null;
        }
        
        try {
            return OBJECT_MAPPER.readValue(jsonBytes, clazz);
        } catch (IOException e) {
            throw new RuntimeException("JSON字节数组转对象失败", e);
        }
    }
    
    /**
     * 输入流转对象
     */
    public static <T> T fromJson(InputStream inputStream, Class<T> clazz) {
        if (inputStream == null) {
            return null;
        }
        
        try {
            return OBJECT_MAPPER.readValue(inputStream, clazz);
        } catch (IOException e) {
            throw new RuntimeException("输入流转对象失败", e);
        }
    }
    
    // ==================== 便捷方法 ====================
    
    /**
     * JSON字符串转List
     */
    public static <T> List<T> toList(String json, Class<T> clazz) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        
        try {
            return OBJECT_MAPPER.readValue(json, 
                OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON转List失败", e);
        }
    }
    
    /**
     * JSON字符串转Map
     */
    public static Map<String, Object> toMap(String json) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        
        try {
            return OBJECT_MAPPER.readValue(json, new TypeReference<Map<String, Object>>() {});
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON转Map失败", e);
        }
    }
    
    /**
     * JSON字符串转指定类型的Map
     */
    public static <K, V> Map<K, V> toMap(String json, Class<K> keyClass, Class<V> valueClass) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        
        try {
            return OBJECT_MAPPER.readValue(json, 
                OBJECT_MAPPER.getTypeFactory().constructMapType(Map.class, keyClass, valueClass));
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON转Map失败", e);
        }
    }
    
    // ==================== JsonNode操作 ====================
    
    /**
     * 字符串转JsonNode
     */
    public static JsonNode parseJson(String json) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        
        try {
            return OBJECT_MAPPER.readTree(json);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON解析失败", e);
        }
    }
    
    /**
     * 对象转JsonNode
     */
    public static JsonNode toJsonNode(Object obj) {
        if (obj == null) {
            return null;
        }
        
        return OBJECT_MAPPER.valueToTree(obj);
    }
    
    /**
     * JsonNode转对象
     */
    public static <T> T fromJsonNode(JsonNode jsonNode, Class<T> clazz) {
        if (jsonNode == null) {
            return null;
        }
        
        try {
            return OBJECT_MAPPER.treeToValue(jsonNode, clazz);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JsonNode转对象失败", e);
        }
    }
    
    // ==================== 工具方法 ====================
    
    /**
     * 判断字符串是否为有效的JSON
     */
    public static boolean isValidJson(String json) {
        if (StringUtils.isEmpty(json)) {
            return false;
        }
        
        try {
            OBJECT_MAPPER.readTree(json);
            return true;
        } catch (JsonProcessingException e) {
            return false;
        }
    }
    
    /**
     * 判断字符串是否为JSON对象
     */
    public static boolean isJsonObject(String json) {
        if (!isValidJson(json)) {
            return false;
        }
        
        try {
            JsonNode node = OBJECT_MAPPER.readTree(json);
            return node.isObject();
        } catch (JsonProcessingException e) {
            return false;
        }
    }
    
    /**
     * 判断字符串是否为JSON数组
     */
    public static boolean isJsonArray(String json) {
        if (!isValidJson(json)) {
            return false;
        }
        
        try {
            JsonNode node = OBJECT_MAPPER.readTree(json);
            return node.isArray();
        } catch (JsonProcessingException e) {
            return false;
        }
    }
    
    /**
     * 合并两个JSON对象
     */
    public static String mergeJson(String json1, String json2) {
        if (StringUtils.isEmpty(json1)) {
            return json2;
        }
        if (StringUtils.isEmpty(json2)) {
            return json1;
        }
        
        try {
            JsonNode node1 = OBJECT_MAPPER.readTree(json1);
            JsonNode node2 = OBJECT_MAPPER.readTree(json2);
            
            if (!node1.isObject() || !node2.isObject()) {
                throw new IllegalArgumentException("只能合并JSON对象");
            }
            
            // 合并逻辑：node2的值会覆盖node1的值
            ObjectMapper mapper = OBJECT_MAPPER.copy();
            JsonNode merged = mapper.readerForUpdating(node1).readValue(node2);
            
            return mapper.writeValueAsString(merged);
        } catch (IOException e) {
            throw new RuntimeException("JSON合并失败", e);
        }
    }
    
    /**
     * 从JSON中提取指定路径的值
     */
    public static JsonNode getValueByPath(String json, String path) {
        if (StringUtils.isEmpty(json) || StringUtils.isEmpty(path)) {
            return null;
        }
        
        try {
            JsonNode rootNode = OBJECT_MAPPER.readTree(json);
            return rootNode.at(path);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON路径提取失败", e);
        }
    }
    
    /**
     * 创建自定义ObjectMapper
     */
    public static ObjectMapper createCustomObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
        return mapper;
    }
    
    /**
     * 获取默认ObjectMapper实例
     */
    public static ObjectMapper getObjectMapper() {
        return OBJECT_MAPPER;
    }
    
    // ==================== 对象拷贝 ====================
    
    /**
     * 通过JSON进行对象深拷贝
     */
    public static <T> T deepCopy(T obj, Class<T> clazz) {
        if (obj == null) {
            return null;
        }
        
        String json = toJson(obj);
        return fromJson(json, clazz);
    }
    
    /**
     * 对象属性拷贝（通过JSON）
     */
    public static <T> T convertObject(Object source, Class<T> targetClass) {
        if (source == null) {
            return null;
        }
        
        return OBJECT_MAPPER.convertValue(source, targetClass);
    }
}
